using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using uTILLIty.Rave.Contract.StorageAdapter;

namespace uTILLIty.Rave.Contract.Configuration
{
	/// <summary>
	/// Represents details about a member of a <see cref="SecurityEntry"/>
	/// </summary>
	public class Member
	{
		private readonly Regex _identifierParseRgex = new Regex(@"(?in)^(?<type>[^=]+)=(?<id>.+)$");
		private string _identifier;
		private bool _identificationTypeSetViaIdentifier;
		private string _identificationType;

		/// <summary>
		/// The default CTOR used by the XML serializer
		/// </summary>
		public Member()
		{
			// ReSharper disable DoNotCallOverridableMethodsInConstructor
			MemberType = MemberType.User;
			// ReSharper restore DoNotCallOverridableMethodsInConstructor
		}

		/// <summary>
		/// Initializes the base <see cref="Member"/> instance
		/// </summary>
		public Member(string id, string identifier, string identificationType, MemberType memberType)
		{
			ID = id;
			// ReSharper disable DoNotCallOverridableMethodsInConstructor
			MemberType = memberType;
			// ReSharper restore DoNotCallOverridableMethodsInConstructor

			//set this BEFORE Identifier, as the identifier might set IdentificationType!
			IdentificationType = identificationType;
			//set this AFTER IdentificationType, as the identifier might set IdentificationType!
			Identifier = identifier;
		}

		/// <summary>
		/// The ID by which this entry is refered to within the configuration
		/// </summary>
		[XmlAttribute("id")]
		public string ID { get; set; }

		/// <summary>
		/// The ID by which this entry is found in the underlying credential store
		/// </summary>
		public string Identifier
		{
			get { return _identifier; }
			set { _identificationTypeSetViaIdentifier = ParseIdentifier(value); }
		}

		/// <summary>
		/// How the <see cref="Identifier"/> is to be interpreted (by the <see cref="IStorageAdapter"/>)
		/// </summary>
		public string IdentificationType
		{
			get { return _identificationType; }
			set
			{
				//required, because deserilization sets "default" value of property 
				if (!_identificationTypeSetViaIdentifier)
					_identificationType = value;
			}
		}

		/// <summary>
		/// The type of member
		/// </summary>
		[DefaultValue(MemberType.User), XmlAttribute("type")]
		public virtual MemberType MemberType { get; set; }

		/// <summary>
		/// Optional additional information validated and used by the <see cref="IStorageAdapter"/>,
		/// to locate the member in the backend user-repository
		/// </summary>
		[XmlElement(IsNullable = false)]
		public AdditionalInformation AdditionalInformation { get; set; }

		/// <summary>
		/// Optional additional creation-information validated and used by the <see cref="IStorageAdapter"/>
		/// to be able to create the member in the backend user-repository, if it could not be located
		/// </summary>
		[XmlElement(IsNullable = false)]
		public CreationConfiguration CreationConfiguration { get; set; }

		/// <summary>
		/// Checks, wether the passed value contains an equal = sign and if so, parses
		/// <see cref="IdentificationType"/> and <see cref="Identifier"/>
		/// </summary>
		protected virtual bool ParseIdentifier(string value)
		{
			var match = _identifierParseRgex.Match(value ?? "");
			if (!match.Success)
			{
				_identifier = value;
				return false;
			}

			_identifier = match.Groups["id"].Value;
			IdentificationType = match.Groups["type"].Value;
			return true;
		}

		/// <summary>
		/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </returns>
		/// <filterpriority>2</filterpriority>
		public override string ToString()
		{
			return string.Format("{0} {{{1}}}", ID, Identifier);
		}
	}
}